﻿using System;
using System.IO;
using System.Text;

namespace UtilZ.Dotnet.Ex.Model
{
    /// <summary>
    /// 数据源读取器
    /// </summary>
    unsafe public class DataSourceReader : BinaryReader
    {
        private readonly DataSource _bufferData;
        /// <summary>
        /// 原始数据源
        /// </summary>
        public DataSource BufferData
        {
            get { return _bufferData; }
        }


        private DataSourceReader(DataSource bufferData, Stream stream)
            : base(stream)
        {
            this._bufferData = bufferData;
        }

        private DataSourceReader(DataSource bufferData, Stream stream, Encoding encoding)
            : base(stream, encoding)
        {
            this._bufferData = bufferData;
        }

        /// <summary>
        /// 创建一个数据源读取对象
        /// </summary>
        /// <param name="bufferData">数据源</param>
        /// <param name="encoding">数据编码类型</param>
        /// <returns>一个数据源读取对象</returns>
        /// <exception cref="NotSupportedException"></exception>
        public static DataSourceReader Create(DataSource bufferData, Encoding encoding = null)
        {
            if (bufferData == null)
            {
                throw new ArgumentNullException(nameof(bufferData));
            }

            Stream stream;
            switch (bufferData.DataType)
            {
#if !NET4_0
                case DataSourceType.Memory:
                    stream = new MemoryStream(bufferData.MemoryBuffer.ToArray());
                    break;
#endif
                case DataSourceType.Bytes:
                    stream = new MemoryStream(bufferData.Bytes);
                    break;
                case DataSourceType.Stream:
                    stream = bufferData.Stream;
                    break;
                case DataSourceType.File:
                    stream = new FileStream(bufferData.FilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                    bufferData.UpdateFileBufferLength(stream.Length);
                    break;
                case DataSourceType.DataPtr:
                    stream = new UnmanagedMemoryStream(bufferData.DataPtr, bufferData.LongLength, bufferData.LongLength, FileAccess.ReadWrite);
                    break;
                default:
                    throw new NotSupportedException(bufferData.DataType.ToString());
            }

            stream.Seek(bufferData.Offset, SeekOrigin.Begin);

            if (encoding == null)
            {
                return new DataSourceReader(bufferData, stream);
            }
            else
            {
                return new DataSourceReader(bufferData, stream, encoding);
            }

        }


        /// <summary>
        /// 重写Dispose
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && this._bufferData.DataType != DataSourceType.Stream)
            {
                base.Dispose(disposing);
            }
        }
    }


}
